#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import sys
import os
import time
import requests
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from config.config import settings
from utils.markdown_parser import MarkdownFormatParser

# 尝试导入智谱AI SDK
try:
    from zhipuai import ZhipuAI
    ZHIPU_AVAILABLE = True
except ImportError:
    ZHIPU_AVAILABLE = False
    print("⚠️ 智谱AI SDK未安装，请运行: pip install zhipuai")

def call_ai_model(prompt):
    """调用AI大模型生成内容"""
    try:
        # 根据配置选择AI模型
        ai_model_type = settings.AI_MODEL_TYPE.lower()
        
        if ai_model_type == "zhipu":
            return call_zhipu_model(prompt)
        elif ai_model_type == "openai":
            return call_openai_model(prompt)
        elif ai_model_type == "qwen":
            return call_qwen_model(prompt)
        elif ai_model_type == "doubao":
            return call_doubao_model(prompt)
        else:
            print(f"⚠️ 不支持的AI模型类型: {ai_model_type}")
            return None
            
    except Exception as e:
        print(f"⚠️ AI模型调用异常: {e}")
        return None

def call_zhipu_model(prompt):
    """调用智谱AI模型"""
    try:
        api_key = settings.ZHIPU_API_KEY
        model = settings.ZHIPU_MODEL
        
        if not api_key:
            print("⚠️ 未配置ZHIPU_API_KEY，使用默认规则生成")
            return None
        
        if not ZHIPU_AVAILABLE:
            print("⚠️ 智谱AI SDK未安装，使用默认规则生成")
            return None
        
        # 使用智谱AI SDK
        client = ZhipuAI(api_key=api_key)
        
        response = client.chat.completions.create(
            model=model,
            messages=[
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            max_tokens=2000,
            temperature=0.7
        )
        
        return response.choices[0].message.content.strip()
            
    except Exception as e:
        print(f"⚠️ 智谱AI模型调用异常: {e}")
        return None

def call_openai_model(prompt):
    """调用OpenAI模型"""
    try:
        api_key = settings.OPENAI_API_KEY
        model = settings.OPENAI_MODEL
        
        if not api_key:
            print("⚠️ 未配置OPENAI_API_KEY，使用默认规则生成")
            return None
        
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        
        data = {
            "model": model,
            "messages": [
                {
                    "role": "system",
                    "content": "你是一个API测试数据生成专家，专门生成各种字段类型的异常值用于测试。"
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            "max_tokens": 2000,
            "temperature": 0.7
        }
        
        response = requests.post(
            "https://api.openai.com/v1/chat/completions",
            headers=headers,
            json=data,
            timeout=settings.REQUEST_TIMEOUT
        )
        
        if response.status_code == 200:
            result = response.json()
            return result["choices"][0]["message"]["content"].strip()
        else:
            print(f"⚠️ OpenAI API调用失败: {response.status_code}")
            return None
            
    except Exception as e:
        print(f"⚠️ OpenAI模型调用异常: {e}")
        return None

def call_qwen_model(prompt):
    """调用通义千问模型"""
    try:
        api_key = settings.QWEN_API_KEY
        model = settings.QWEN_MODEL
        
        if not api_key:
            print("⚠️ 未配置QWEN_API_KEY，使用默认规则生成")
            return None
        
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        
        data = {
            "model": model,
            "messages": [
                {
                    "role": "system",
                    "content": "你是一个API测试数据生成专家，专门生成各种字段类型的异常值用于测试。"
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            "max_tokens": 2000,
            "temperature": 0.7
        }
        
        response = requests.post(
            "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
            headers=headers,
            json=data,
            timeout=settings.REQUEST_TIMEOUT
        )
        
        if response.status_code == 200:
            result = response.json()
            return result["output"]["text"].strip()
        else:
            print(f"⚠️ 通义千问API调用失败: {response.status_code}")
            return None
            
    except Exception as e:
        print(f"⚠️ 通义千问模型调用异常: {e}")
        return None

def call_doubao_model(prompt):
    """调用豆包AI模型"""
    try:
        api_key = settings.DOUBAO_API_KEY
        model = settings.DOUBAO_MODEL
        base_url = settings.DOUBAO_BASE_URL
        
        if not api_key:
            print("⚠️ 未配置DOUBAO_API_KEY，使用默认规则生成")
            return None
        
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        
        data = {
            "model": model,
            "messages": [
                {
                    "role": "system",
                    "content": "你是一个API测试数据生成专家，专门生成各种字段类型的异常值用于测试。"
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            "max_tokens": 2000,
            "temperature": 0.7
        }
        
        response = requests.post(
            base_url,
            headers=headers,
            json=data,
            timeout=settings.REQUEST_TIMEOUT
        )
        
        if response.status_code == 200:
            result = response.json()
            return result["choices"][0]["message"]["content"].strip()
        else:
            print(f"⚠️ 豆包AI API调用失败: {response.status_code}")
            print(f"响应内容: {response.text}")
            return None
            
    except Exception as e:
        print(f"⚠️ 豆包AI模型调用异常: {e}")
        return None

def generate_invalid_values_with_ai():
    """使用AI生成异常值集合"""
    
    # 动态读取markdown文档获取格式规范
    print("🔄 正在解析markdown格式规范文档...")
    parser = MarkdownFormatParser()
    format_summary = parser.generate_format_summary()
    
    if "无法解析格式规范文档" in format_summary:
        print("⚠️ 无法解析格式规范文档，使用默认规范")
        format_summary = """
参考格式规范（默认规范）：
- text: 最大长度100字符
- bigint: 18位以内整数（-999999999999999999 ~ 999999999999999999）
- number: 整数部分≤18位，小数部分≤9位
- date: 格式YYYY-MM-DD
- datetime: 支持字符串格式"YYYY-MM-DD HH:MM:SS"或时间戳
- mobile_number: 包含dialing_code、country_code、number三个字段，number为11位数字
- email: 包含@且@后有有效域名
- option: 值必须为预设optionList中的apiName
- boolean: 仅支持true或false
- multilingual: 包含zh_CN和/或en_US的对象，总字符数0-1000
- decimal: 整数部分≤18位，小数部分≤9位
"""
    
    # 获取字段类型列表
    field_types = parser.get_field_types()
    if not field_types:
        field_types = [
            "text", "bigint", "number", "date", "datetime", 
            "mobile_number", "email", "option", "boolean", 
            "avatar_or_logo", "multilingual", "region", "decimal"
        ]
    
    # 构建优化的提示词
    prompt = f"""
你是一个API测试数据生成专家。我需要为以下字段类型生成异常值集合，用于API测试。

字段类型列表：
{chr(10).join([f"- {field_type}" for field_type in field_types])}

{format_summary}

任务要求：
1. 为每种字段类型生成10个异常值
2. 异常值应该覆盖各种常见的错误情况：
   - 格式错误（如日期格式错误、邮箱格式错误）
   - 长度超限（如文本过长、数字超出范围）
   - 类型错误（如布尔值用字符串表示）
   - 缺失必填字段（如手机号缺少country_code）
   - 无效值（如选项值不在预设列表中）
   - 边界值错误（如负数、零值、极大值等）

3. 返回格式必须是有效的JSON，结构如下：
{{
{chr(10).join([f'  "{field_type}": ["异常值1", "异常值2", ...],' for field_type in field_types])}
}}

注意：
- 每个字段类型必须生成10个异常值
- 异常值应该是字符串格式，即使是数字类型也要用引号包围
- 确保JSON格式正确，可以被解析
- 对于复杂类型（如mobile_number、multilingual），异常值应该是完整的JSON字符串
- 不要包含任何解释文字，只返回JSON格式的数据

请生成符合要求的异常值集合：
"""

    # 调用AI模型
    print(f"🔄 正在调用AI生成异常值集合...")
    print(f"AI模型类型: {settings.AI_MODEL_TYPE}")
    
    ai_response = call_ai_model(prompt)
    
    if ai_response:
        print(f"✅ AI返回原始内容:")
        print(f"---AI开始---")
        print(ai_response)
        print(f"---AI结束---")
        
        try:
            # 尝试解析JSON
            # 清理可能的markdown格式
            cleaned_response = ai_response.strip()
            cleaned_response = cleaned_response.replace('```json', '').replace('```', '')
            cleaned_response = cleaned_response.strip()
            
            # 解析JSON
            invalid_values = json.loads(cleaned_response)
            
            # 验证结构
            for field_type in field_types:
                if field_type not in invalid_values:
                    print(f"⚠️ 缺少字段: {field_type}")
                    invalid_values[field_type] = []
                elif not isinstance(invalid_values[field_type], list):
                    print(f"⚠️ 字段 {field_type} 不是列表类型")
                    invalid_values[field_type] = []
                elif len(invalid_values[field_type]) < 10:
                    print(f"⚠️ 字段 {field_type} 异常值数量不足10个，当前: {len(invalid_values[field_type])}")
            
            return invalid_values
            
        except json.JSONDecodeError as e:
            print(f"❌ AI返回的JSON格式错误: {e}")
            print(f"AI返回内容: {ai_response}")
            return None
        except Exception as e:
            print(f"❌ 解析AI返回内容时出错: {e}")
            print(f"AI返回内容: {ai_response}")
            return None
    else:
        print(f"❌ AI调用失败，返回None")
        return None

def generate_default_invalid_values():
    """生成默认的异常值集合（备用方案）"""
    return {
        "text": [
            "这是一个超过100个字符的异常文本，用来测试文本字段的长度限制。这个文本应该会被系统拒绝，因为它超过了最大长度限制。",
            "",
            None,
            "特殊字符测试：!@#$%^&*()_+-=[]{}|;':\",./<>?",
            "数字文本123456789",
            "Unicode字符测试：中文测试🎉🚀💻",
            "重复字符测试：aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "换行符测试\n\n\n",
            "制表符测试\t\t\t",
            "空格测试     "
        ],
        "bigint": [
            "1234567890123456789",  # 19位，超出18位限制
            "-1234567890123456789",  # 19位负数
            "9999999999999999999",  # 超出范围
            "abc",  # 非数字
            "12.34",  # 浮点数
            "0",  # 零值
            "-0",  # 负零
            "1e18",  # 科学计数法
            "1,234,567,890",  # 带逗号
            "12 34 56"  # 带空格
        ],
        "number": [
            "1234567890123456789.1",  # 整数部分19位
            "123.1234567890",  # 小数部分10位
            "abc",  # 非数字
            "1e20",  # 超出范围
            "0",  # 零值
            "-0",  # 负零
            "1,234.56",  # 带逗号
            "12 34.56",  # 带空格
            "12.34.56",  # 多个小数点
            "12.34e5"  # 科学计数法
        ],
        "date": [
            "2025-13-01",  # 无效月份
            "2025-02-30",  # 2月30日不存在
            "2025/03/31",  # 格式错误
            "2025-03-31 12:00:00",  # 包含时间
            "abc",  # 非日期
            "2025-00-01",  # 月份为0
            "2025-03-00",  # 日期为0
            "2025-3-1",  # 缺少前导零
            "2025-03-1",  # 日期缺少前导零
            "2025-3-31"  # 月份缺少前导零
        ],
        "datetime": [
            "2025-03-31-08:00:00",  # 格式错误，应该用空格
            "2025-03-31 09:00",  # 缺少秒数
            "2025-03-31 25:00:00",  # 小时超出范围
            "2025-03-31 12:60:00",  # 分钟超出范围
            "abc",  # 非日期时间
            "2025-03-31",  # 缺少时间部分
            "1750927056368abc",  # 时间戳包含非数字
            "2025-03-31 12:00:00+25",  # 时区超出范围
            "2025-03-31 12:00:00+08:30",  # 时区格式错误
            "2025-03-31 12:00:00+0800"  # 时区格式错误
        ],
        "mobile_number": [
            '{"number": "13800000000"}',  # 缺少必填字段
            '{"dialing_code": "+86", "country_code": "CN"}',  # 缺少number
            '{"dialing_code": "+86", "country_code": "CN", "number": "138000000"}',  # 号码不足11位
            '{"dialing_code": "+86", "country_code": "CN", "number": "138000000000"}',  # 号码超过11位
            '{"dialing_code": "86", "country_code": "CN", "number": "13800000000"}',  # 缺少+号
            '{"dialing_code": "+86", "country_code": "CN", "number": "1380000000a"}',  # 包含字母
            '{"dialing_code": "+86", "country_code": "CN", "number": "1380000000 "}',  # 包含空格
            '{"dialing_code": "+86", "country_code": "XX", "number": "13800000000"}',  # 无效国家代码
            '{"dialing_code": "+999", "country_code": "CN", "number": "13800000000"}',  # 无效拨号代码
            '{"dialing_code": "+86", "country_code": "CN", "number": "00000000000"}'  # 全零号码
        ],
        "email": [
            "test@",  # 缺少域名
            "@domain.com",  # 缺少用户名
            "test.domain.com",  # 缺少@符号
            "test@domain",  # 域名不完整
            "test..name@domain.com",  # 连续点号
            "test@.domain.com",  # 域名以点开始
            "test@domain..com",  # 域名包含连续点号
            "test name@domain.com",  # 包含空格
            "test@domain.com.",  # 以点结束
            "test@domain@com"  # 多个@符号
        ],
        "option": [
            "invalid_option",  # 无效选项
            "option_999999",  # 不存在的选项
            "random_text",  # 随机文本
            "123",  # 数字
            "",  # 空字符串
            "option_",  # 不完整的选项名
            "OPTION_52d86948bb9",  # 大小写错误
            "option_52d86948bb9_extra",  # 额外后缀
            "option_52d86948bb9 ",  # 包含空格
            "option_52d86948bb9\n"  # 包含换行符
        ],
        "boolean": [
            "true",  # 字符串true
            "false",  # 字符串false
            "1",  # 数字1
            "0",  # 数字0
            "yes",  # 字符串yes
            "no",  # 字符串no
            "TRUE",  # 大写TRUE
            "FALSE",  # 大写FALSE
            "True",  # 首字母大写
            "False"  # 首字母大写
        ],
        "avatar_or_logo": [
            "invalid_url",  # 无效URL
            "https://invalid-domain.com/image.jpg",  # 无效域名
            "ftp://example.com/image.jpg",  # 不支持的协议
            "",  # 无效base64
            "image.jpg",  # 相对路径
            "/path/to/image.jpg",  # 绝对路径
            "https://example.com/image.jpg?invalid=param",  # 包含参数
            "https://example.com/image.jpg#fragment",  # 包含片段
            "https://example.com/image.jpg ",  # 包含空格
            "https://example.com/image.jpg\n"  # 包含换行符
        ],
        "multilingual": [
            '{"zh_CN": "测试文本"}',  # 只有中文
            '{"en_US": "Test text"}',  # 只有英文
            '{"zh_CN": "测试文本", "en_US": "Test text"}',  # 正常格式
            '{"zh_CN": "这是一个超过1000字符的异常文本..."}',  # 超长文本
            '{"invalid_key": "test"}',  # 无效键名
            '{"zh_CN": 123}',  # 值不是字符串
            '{"zh_CN": null}',  # null值
            '{"zh_CN": ""}',  # 空字符串
            '{"zh_CN": "测试文本", "extra": "extra"}',  # 额外字段
            '{"zh_CN": "测试文本", "en_US": 123}'  # 混合类型
        ],
        "region": [
            '{"invalid": "region"}',  # 无效格式
            '{"fullPath": "invalid"}',  # 格式错误
            '{"fullPath": [{"text": "北京"}]}',  # 缺少language_code
            '{"fullPath": [{"language_code": 2052}]}',  # 缺少text
            '{"fullPath": [{"language_code": "invalid", "text": "北京"}]}',  # 无效language_code
            '{"fullPath": [{"language_code": 2052, "text": ""}]}',  # 空文本
            '{"fullPath": [{"language_code": 2052, "text": "北京"}], "level": "invalid"}',  # 无效level
            '{"fullPath": [{"language_code": 2052, "text": "北京"}], "isDeleted": "invalid"}',  # 无效isDeleted
            '{"fullPath": [{"language_code": 2052, "text": "北京"}], "extra": "extra"}',  # 额外字段
            '{"fullPath": [{"language_code": 2052, "text": "北京", "extra": "extra"}]}'  # 额外字段
        ],
        "decimal": [
            "1234567890123456789.1",  # 整数部分19位
            "123.1234567890",  # 小数部分10位
            "abc",  # 非数字
            "1e20",  # 超出范围
            "0",  # 零值
            "-0",  # 负零
            "1,234.56",  # 带逗号
            "12 34.56",  # 带空格
            "12.34.56",  # 多个小数点
            "12.34e5"  # 科学计数法
        ]
    }

def main():
    """主函数"""
    print("=" * 60)
    print("异常值集合生成器 - 动态读取markdown文档版本")
    print("=" * 60)
    
    # 尝试使用AI生成
    invalid_values = generate_invalid_values_with_ai()
    
    # 如果AI生成失败，使用默认值
    if not invalid_values:
        print("🔄 AI生成失败，使用默认异常值集合...")
        invalid_values = generate_default_invalid_values()
    
    # 保存到文件
    output_file = "data/invalidCollection.json"
    
    # 确保目录存在
    os.makedirs(os.path.dirname(output_file), exist_ok=True)
    
    with open(output_file, 'w', encoding='utf-8') as f:
        json.dump(invalid_values, f, 
                 ensure_ascii=False,  # 确保非ASCII字符正常显示
                 indent=2,            # 缩进格式化
                 sort_keys=True)
    
    print(f"\n✅ 成功生成异常值集合并保存到 {output_file}")
    
    # 统计信息
    print(f"\n📊 异常值集合统计:")
    for field_type, values in invalid_values.items():
        print(f"  {field_type}: {len(values)} 个异常值")
    
    # 显示前几个示例
    print(f"\n📝 示例异常值:")
    for field_type, values in list(invalid_values.items())[:3]:
        print(f"  {field_type}:")
        for i, value in enumerate(values[:3]):
            print(f"    {i+1}. {value}")

if __name__ == "__main__":
    main() 